package piechowicz.szymon.fft.samples.basic;

import piechowicz.szymon.fft.Complex;
import piechowicz.szymon.fft.FFT;

public class Basic
{
    
    static final double EPSILON = 0.000001;
    static final int n = 1024;
    
    final FFT dft = new FFT(n, false);
    final FFT idft = new FFT(n, true);

    public Basic()
    {
        System.out.println("Testing if transform computes correct intensity: "
                + (test_transform_intensity() ? "OK" : "FAILED"));
        System.out.println("Testing if transform computes correct phase: "
                + (test_transform_phase() ? "OK" : "FAILED"));
        System.out.println("Testing if inverse transform works: "
                + (test_inverse_transform() ? "OK" : "FAILED"));
    }

    private boolean test_transform_intensity()
    {
        int d = 10;
        Complex[] v = new Complex[n];
        for (int i = 0; i < n; ++i)
            v[i] = new Complex(Math.cos(2 * Math.PI * d * i / n));
        Complex[] v_dft = dft.transform(v);
        for (int k = 0; k < (n >> 1); ++k)
        {
            if (k == d && FFT.getIntensity(v_dft[k]) <= EPSILON)
                return false;
            if (k != d && FFT.getIntensity(v_dft[k]) > EPSILON)
                return false;
        }            
        return true;
    }

    private boolean test_transform_phase()
    {
        int d = 10;
        double phase = Math.PI / 4.0;
        Complex[] v = new Complex[n];
        for (int i = 0; i < n; ++i)
            v[i] = new Complex(Math.cos(2 * Math.PI * d * i / n + phase));
        Complex[] v_dft = dft.transform(v);
        return Math.abs(FFT.getPhase(v_dft[d]) - phase) < EPSILON;
    }

    private boolean test_inverse_transform()
    {
        Complex[] v = new Complex[n];
        for (int i = 0; i < n; ++i)
            // some function
            v[i] = new Complex(
                    Math.cos(2 * Math.PI * 10 * i / n)
                    * Math.sin(2 * Math.PI * 17 * i / n)
                    );
        Complex[] v_restored = idft.transform(dft.transform(v));
        for (int k = 0; k < n; ++k)
            if (v_restored[k].minus(v[k]).abs() > EPSILON)
                return false;
        return true;
    }

}
